package com.mdl.springmvc.handler;

import org.springframework.web.server.handler.ResponseStatusExceptionHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;

/**
 * @Desc
 * @Author madengling
 * @Time 2020/12/10 17:33
 */
public class Biji {
/*
48.自定义拦截器
--SpringMVC也可以使用拦截器对请求进行拦截处理，用户可以自定义拦截器来实现特定的功能，自定义的拦截器必须实现HandlerInterceptor接口
1.preHandler():这个方法在业务处理器处理请求之前被调用，在该方法中对用户请求request进行处理。如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器，
或者是业务处理器去进行处理，则返回true；如果程序员决定不需要再调用其他的组件去处理请求，则返回false。
2.postHandle():这个方法在业务处理器处理完请求后，但是DispatcherServlet向客户端返回响应前被调用，在该方法中对用户请求request进行处理。
3.afterCompletion():这个方法在DispatcherServlet完全处理完请求后被调用，可以在该方法中进行一些资源清理的操作。

-拦截器方法执行顺序
FirstInterceptor#preHandle--->HandleAAdapter#handle--->FirstInterceptor#postHandle--->DispatcherServlet--->FirstInterceptor#afterCompletion

FirstInterceptor#preHandle      --->    SecondInterceptor#preHandle
                                                   │
                                        HandleAAdapter#handle
                                                   │
FirstInterceptor#postHandle     <---    SecondInterceptor#postHandle
                │
                │------------------>    DispatcherServlet
                                                   │
FirstInterceptor#afterCompletion<---    SecondInterceptor#afterCompletion

                                        return false
FirstInterceptor#preHandle      --->    SecondInterceptor#preHandle
                                                   │
                 <---------------------------------│
                │
FirstInterceptor#afterCompletion<---    SecondInterceptor#afterCompletion
注：interceptorIndex默认为-1，存在一个默认的=1=0，之后执行一个preHandle+1，根据参数执行afterCompletion释放资源

51.异常处理_ExceptionHandler注解

-异常处理
--SpringMVC通过HandlerExceptionResolver处理程序的异常，包括Handler映射、数据绑定以及目标方法执行时发生的异常。
--SpringMVC提供的HandlerExceptionResolver的实现类
#####HandlerExceptionResolver

--HandlerExceptionResolver
---DispatcherServlet默认装配的HandlerExceptionResolver：
1.没有使用<mvc:annotation-driven/>配置：AnnotationMethodHandlerExceptionResolver，ResponseStatusExceptionResolver，DefaultHandlerExceptionResolver
2.使用了<mvc:annotation-driven/>配置：ExceptionHandlerExceptionResolver，ResponseStatusExceptionResolver，DefaultHandlerExceptionResolver

--ExceptionHandlerExceptionResolver
--主要处理Handler中用@ExceptionHandler注解定义的方法。
--@ExceptionHandler注解定义的方法优先级问题：例如发生的是NullPointerException，但是声明的异常有RuntimeException和Exception，此时会根据异常的最近继承关系找到继承深度最浅的那个
@ExceptionHandler注解方法，即标记了RuntimeException的方法
--ExceptionHandlerMethodResolver内部若找不到@ExceptionHandler注解的话，会找@ControllerAdvice中的@ExceptionHandler注解方法

-ResponseStatusExceptionHandler
--在异常及异常父类中找到@ResponseStatus注解，然后使用这个注解的属性进行处理。
--定义一个@ResponseStatus注解修饰的异常类
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public class UnauthorizedException extends RuntimeException{}
--若在处理器方法中跑出来上述异常：若ExceptionHandlerExceptionResolver不解析上述异常。由于触发的异常UnauthorizedException带有@ResponseStatus注解。因此会被
ResponseStatusExceptionHandler解析到。最后响应HttpStatus.UNAUTHORIZED代码给客户端。HttpStatus.UNAUTHORIZED代表响应码401，无权限。关于其他的响应码请参考HttpStatus枚举类型源码。
#####ResponseStatusExceptionHandler

-DefaultHandlerExceptionResolver
--对一些特殊的异常进行处理，比如NoSuchRequestHandingMethodException、HttpRequestMethodNotSupportedException、
HttpMediaTypeNotSupportedException、HttpMediaTypeNotAcceptableException等。
#####DefaultHandlerExceptionResolver

-SimpleMappingExceptionResolver
--如果希望对所有异常进行统一处理，可以使用SimpleMappingExceptionResolver，它将异常类名映射为视图名，即发生异常时使用对应的视图报告异常
#####SimpleMappingExceptionResolver

55.SpringMVC运行流程图解
              请求
                │
springDispatcherServlet的url-pattern
                │
SpringMVC中刷存在对应的映射？--->存在--->由HandlerMapping获取HandlerExceptionChain对象--->获取HandlerAdapter对象
           不存在│                                                                               │
是否配置<mvc:default-servlet-handler/>--->有配置--->目标资源                            调用拦截器的preHandle方法
             木有│                                                                               │
控制台：No mapping found for HTTP request with                               调用目标Handler的目标方法得到ModelAndView对象
URL[/xx/xxx] in DispatcherServlet、404页面                                                       │
                                                                                                │
                             存在---------------------是否存在异常<-------------------调用拦截器的postHandle方法
                              │                           │
                              │                           │----------------------------------> 不存在
                              │                                                                  │
由HandlerExceptionResolver组件处理异常，得到新的ModelAndView对象------------>由ViewResolver组件根据ModelAndView对象得到实际的view
                                                                                                 │
                             调用拦截器的afterCompletion方法<-----------------------------------渲染视图

57.Spring整合SpringMVC
需要进行Spring整合SpringMVC吗？
还是否需要再加Spring的IOC容器吗？
是否需要在web.xml文件中配置启动SpringIOC容器的ContextLoaderListener？

1.需要：通常情况下，类似于数据源，事务，整合其他框架都是放在Spring的配置文件中（而不是放在SpringMVC的配置文件中）。
实际上放入Spring配置文件对应的IOC容器中的还有Service和Dao
2.不需要：都放在SpringMVC的配置文件中，也可以分多个Spring的配置文件，然后使用import节点导入其他的配置文件

问题：若Spring的IOC容器和SpringMVC的IOC容器扫描的包有重合的部分，就会导致有的bean会被创建两次
解决：
1.使Spring的IOC容器扫描的包和SpringMVC的IOC容器扫描的包没有重合的部分。
2.使用exclude-filter和include-filter子节点来规定只能扫描的注解

59.SpringIOC容器和SpringMVC IOC容器的关系
SpringMVC的IOC容器中的bean可以来引用SpringIOC容器中的bean。
反之则不行。SpringIOC容器中的bean却不能来引用SpringMVC IOC容器中的bean！

-在SpringMVC配置文件中引用业务层的Bean
--多个SpringIOC容器之间可以设置为父子关系，以实现良好的解耦。
--SpringMVC WEB层容器可作为“业务层”
Spring容器的子容器：即WEB层容器可以引用业务层容器的Bean，而业务层容器却访问不到WEB层容器的Bean

60.SpringMVC对比Struts2
--SpringMVC的入口是Servlet，而Struts2是Filter
--SpringMVC会稍微比Struts2快些。SpringMVC是基于方法设计，而Struts2是基于类，每次发一次请求都会实例一个Action
--SpringMVC使用更加简洁，开发效率SpringMVC确实比Struts2高：支持JSR303，处理ajax的请求更方便
--Struts2的OGNL表达式是页面的开发效率相比SpringMVC更高些。


 */



}
